Skip to content

Honor per-auth request_retry override for unexpected-EOF retries#3

Merged
hex-ci merged 1 commit into
mainfrom
devin/1780645724-eof-per-auth-retry
Jun 5, 2026
Merged

Honor per-auth request_retry override for unexpected-EOF retries#3
hex-ci merged 1 commit into
mainfrom
devin/1780645724-eof-per-auth-retry

Conversation

@devin-ai-integration

Copy link
Copy Markdown

Summary

Addresses the P2 review comment on router-for-me#3726: the statusless "unexpected EOF" fast path used retryAllowed(attempt, providers), which returns true if any auth in the provider still has retries. So a request running on a credential whose auth file sets request_retry: 0 would still retry its EOF as long as a sibling credential allowed retries — bypassing the per-auth override that the cooldown path already honors.

Fix: scope the EOF retry decision to the credential that actually failed.

  • shouldRetryAfterError(..., failedAuthID string) now receives the failed auth ID. The three Execute* loops thread it in via a *string out-param set in executeMixedOnce / executeCountMixedOnce / executeStreamMixedOnce right after the auth is selected (the last selected auth is the one tied to the returned error).
  • New eofRetryAllowed consults the failed auth's own effective retry; falls back to the provider-wide retryAllowed when the auth is unknown:
if status == 0 && isUnexpectedEOFError(err) {
    if !m.eofRetryAllowed(attempt, providers, failedAuthID) { // was: m.retryAllowed(attempt, providers)
        return 0, false
    }
    return 0, true
}

func (m *Manager) eofRetryAllowed(attempt int, providers []string, failedAuthID string) bool {
    if allowed, known := m.authRetryAllowed(attempt, failedAuthID); known {
        return allowed // honors auth.RequestRetryOverride()
    }
    return m.retryAllowed(attempt, providers)
}

Why an out-param instead of reading opts.Metadata[selected_auth_id] in the outer loop: ensureRequestedModelMetadata may copy opts.Metadata into a fresh map inside the once-functions, so the outer opts doesn't reliably see the selected auth. The SelectedAuthCallbackMetadataKey callback is already used by handlers.go, so overwriting it was not an option.

Statusless EOF on a retry-enabled credential is unchanged; only the disabled-credential case now stops retrying.

Test

  • Added TestManager_ShouldRetryAfterError_UnexpectedEOFRespectsAuthRequestRetryOverride: two claude auths (one request_retry: 0, one default). EOF on the disabled auth → no retry; EOF on the enabled auth → retry; unknown auth → falls back to provider-wide retry.
  • gofmt -w, go build ./..., go vet, and go test ./... all pass.

Link to Devin session: https://app.devin.ai/sessions/eb1be9597f8d44c9af3d671e9fda7c03
Requested by: @hex-ci

Co-Authored-By: Hex <hex@codeigniter.org.cn>
@devin-ai-integration

Copy link
Copy Markdown
Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@hex-ci hex-ci merged commit c67f875 into main Jun 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant